CPP|一个简单的变量声明背后复杂的语法概念与存储实现

为了有效地完成数据存储任务,需要对存储器做如下处理:

1 划分:以字节(8个位bit,对应8个开关晶体管,0或1)为单位将存储器划分为一系列的存储单元。

2 编址:以线性方式给每个存储单元赋予唯一的存储地址,可以随机访问。

3 数据存储约定:数据以二进制形式放入存储空间,需要约定数据的存储空间大小、存储空间地址、数据编码和解码方式以及字节排序方式。如一个基本类型需要多字节时,用大头地址还是小头地址做为数据的地址?

3.1 数据的编码和解码方式

I 以补码方式存储整数;C++|一个简单的变量声明背后复杂的语法概念与存储实现

II 通过ASCII编码方式存储字符;

III 以real-4或real-8方式存储浮点数(实数或小数);

3.2 大头还是小头,按理说只要统一约定就好,但是Intel公司的机器多采用小头方式,IBM、Sun等公司采用大头方式。一般情况下,可以不考虑字节排序方式的问题,但是在针对网络应用编写程序时,就必须关注使用哪种字节排序方式,这是因为网络程序通常需要在不同类型的机器之间交换数据。

为什么是不个bit为一个byte做为最小(基本)的存储单元呢?2^3=8,指数计算方便,另位2^8=256,能够包含全部英文字母+数字+一些基本常用的符号。

下面的变量声明和定义就暗含了上面全部的内容。

double PriceOfRice;

数据=数据规格(类型)+数据地址(变量名)

数据规格=存储空间大小+编码和解码方式+可接受的运算处理

1 在内存中开辟一个8个字节的内存单元,可以通过sizeof(double)得到字节数;

2 该段内存单元的地址用PriceOfRice来表示;

3 此时的值是一个随机值,因为每个字节的每个位都是随机的0或1。如此时用代码cout<<PriceOfRice访问其值,可以显示:-9.25596e+0618,但你在一些操作后再去访问,其值可能不一样了。

另外,PriceOfRice的取名有诸多要求和考究,例如,不能使用关键字,不能用数字开头,如建议能见名知义,通过名字而不是通过注释去了解其含义。

给变量赋值:

PriceOfRice =3.18;

3.18是字面量,属于代码部分,不可寻址,3.18按real-8的编码方案编码(一串01)后放到PriceOfRice对应的内存空间(每个比特或0或1)。

字面量写法:

浮点型字面量也可以写成.46、1.e20、2.3f、123e12、1.e4L、-.34e-2f;

整形字面量:157、-0655、0xFE、-0x1UL;

字符型字面量:'C'、'ab'、'$'、'\n'、'\x61'、L'中'、L'a';

布尔型字面量:true、false;

字符串型字面量:"C++ programming"、L"abc"、"\x41\x42\x43"(ABC);

除了字符串型字面量,其它字面量都不可寻址,字符串型字面量存储在被分配的内存空间的数据段。

另外,两行代码写到一起:double PriceOfRice =3.18;

表示变量声明、定义、初始化同时完成。

关于初始化的内容,请见:《C++|变量、对象、对象成员初始化的一些细节》。

对于代码:PriceOfRice = PriceOfRice *1.1

表示右边的PriceOfRice表示取值,乘以1.1,按double的编码方案编码后放到左边的PriceOfRice对应的内存单元。

C++左值和右值的概念:左值表示一种可以定位的存储空间,右值表示从存储空间中临时读取的数据值。左值可以做右值,右值不能用做左值。

而乘法运算符*则表示了double这种类型可接受的运算处理,如double就能不使用取余运算符%,而指针类型一般不会使用*来做运算(指针一般用其做解运算)。

下面是一个关于整数编码的小实例:

#include <iostream>

using namespace std;

int main()

{

unsigned long unl = -0x1UL;

unsigned long ul = 0x1UL;

long l = -0x1L;

cout<<unl<<endl;//4294967295

cout<<ul<<endl;//1

cout<<l<<endl;//-1

cout<<hex<<unl<<endl;

cout<<ul<<endl;

cout<<l<<endl;

cout<<sizeof(long)<<endl;

//正数的原码、反码、补码都相同

//负数补码:原码的符号位(最高位)不变,其余位取反,然后再加1

//原码:10000000 00000000 00000000 00000001(最高位是符号位)

//反码:11111111 11111111 11111111 11111110(符号位不变,其余取反)

//补码:11111111 11111111 11111111 11111111(反码加1)

system("pause");

return 0;

}

/*

4294967295

1

-1

ffffffff

1

ffffffff

4

*/

另外,double PriceOfRice;写在不同的位置,或者前面有诸如static、external等不同的限定词,决定了其有不同的作用域和存续期,同时也确定了其存储在被分配给程序的一块内存空间中不同的区域(栈区、全局区\静态区等)。

变量规定了名字和数据类型的存储空间,执行程序就是促使变量的存储空间状态发生变化,并达到预期状态的。因此,编程时应该能够随时在大脑中描绘出变量相对应的存储空间状态,称为存储空间映像。

-End-

本页共71段,2476个字符,5289 Byte(字节)